﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using WU.LoadTester.Lib.Service;

namespace WU.LoadTester.Lib
{
    public class LogFile
    {
        private static StreamWriter _instance;
        public static string Path;
        private static int _maxLength;
        private static object _lock = new object();
        public delegate void WriteHandler(string text);
        public static event WriteHandler OnWrite;

        public LogFile(string path, int length)
        {
            if (_instance == null && path != null)
            {
                var dir = new DirectoryInfo(String.Format(@"{0}\logs", path));
                if(!dir.Exists)
                    dir.Create();
                Path = String.Format(@"{0}\logs\{1}_wuload.log", path, DateTime.Now.ToFileTime());
                _instance = new StreamWriter(Path, false, Encoding.UTF8);
            }
            _maxLength = length;
        }

        public static void WriteLine(string line)
        {
            lock(_lock)
            {
                if (_instance != null)
                {
                    _instance.WriteLine(line);
                    _instance.Flush();
                }

                if(OnWrite != null)
                {
                    OnWrite.Invoke(line);
                }
            }
        }

        public static void WriteResult(string method, IEnumerable<string>parameters, Result result)
        {
            lock(_lock)
            {
                string line = string.Format("{0, -12}{1, -10}{2, -35}{3, -" + _maxLength.ToString() + "}{4}",
                              new object[] { DateTime.Now.ToLongTimeString(), result.ResponseTime.Milliseconds.ToString(), method, parameters.Aggregate((s1, s2) => s1 + "," + s2), result.Message });

                if (_instance != null)
                {
                    _instance.WriteLine(line);
                    _instance.Flush();
                }

                if (OnWrite != null)
                {
                    OnWrite.Invoke(line);
                }
            }
        }

        public static void WriteEx(Exception ex)
        {
            lock (_lock)
            {
                string strEx = string.Format("{0} ******** Exception {1} ******** Message {2} ******** Inner Execption {3} ******** Stack Trace {4} \n",
                    new object[]{ DateTime.Now.ToLongTimeString(), ex.GetType(), ex.Message, ex.InnerException != null ? ex.InnerException.Message : string.Empty, ex.StackTrace});
                
                if (_instance != null)
                {
                    _instance.WriteLine(strEx);
                    _instance.Flush();
                }

                if (OnWrite != null)
                {
                    OnWrite.Invoke(strEx);
                }
            }
        }
        public static void DumpHeader(Settings settings)
        {
            lock (_lock)
            {
                if (_instance != null)
                {
                    //Dump info in log
                    _instance.WriteLine(String.Format("{0} ******** Testing started on endpoint {1} ********",
                                                      DateTime.Now.ToLongTimeString(), settings.EndpointAddress));
                    _instance.WriteLine(string.Empty);
                    _instance.WriteLine(string.Empty);
                    _instance.WriteLine(String.Format("{0} ******** Settings ******", DateTime.Now.ToLongTimeString()));
                    _instance.WriteLine(String.Format("{0} ******** CSVFile   : {1}", DateTime.Now.ToLongTimeString(),
                                                      settings.CSVFilepath));
                    _instance.WriteLine(String.Format("{0} ******** Call type : {1}", DateTime.Now.ToLongTimeString(),
                                                      settings.CallType.ToString()));
                    _instance.WriteLine(String.Format("{0} ******** Service type : {1}", DateTime.Now.ToLongTimeString(),
                                  settings.ClientType.ToString()));
                    _instance.WriteLine(String.Format("{0} ******** Threads   : {1}", DateTime.Now.ToLongTimeString(),
                                                      settings.Threads.ToString()));
                    _instance.WriteLine(string.Empty);
                    _instance.WriteLine(string.Empty);
                    _instance.WriteLine(string.Format("{0, -12}{1, -10}{2, -35}{3, -" + _maxLength.ToString() + "}{4}",
                                                      new object[]
                                                          {"Time", "Call (ms)", "Method", "Parameter", "Result"}));
                }

                if(OnWrite != null)
                {
                    string header = string.Format("{0, -12}{1, -10}{2, -35}{3, -" + _maxLength.ToString() + "}{4}",
                                  new object[] { "Time", "Call (ms)", "Method", "Parameter", "Result" });
                    OnWrite.Invoke(header);
                }
            }
        }
    }
}
